'use strict';
// 引入
const fs = require('fs');
const path = require('path');
const Controller = require('egg').Controller;

class FileController extends Controller {
    // 创建文件夹
    async createdir() {
        const { ctx, app } = this;
        const user_id = ctx.authUser.id;

        ctx.validate({
            dir_id: {
                required: false,
                type: "int",
                defValue: 0,
                desc: "目录id"
            },
            name: {
                required: true,
                type: "string",
                desc: "文件夹名称"
            }
        });

        let { dir_id, name } = ctx.request.body;

        // 验证父目录id是否存在
        if (dir_id) {
            await this.service.file.isDirExist(dir_id);
        }

        if (await app.model.File.count({ where: { dir_id, name } }) > 0) {
            this.ctx.throw(422, "与该目录下文件夹名称重复");
        }

        let res = await app.model.File.create({
            name,
            dir_id,
            user_id,
            isdir: 1,
            size: 0
        });

        ctx.apiSuccess(res);
    }
    // 上传
    async upload() {
        const { ctx, app } = this;
        const currentUser = ctx.authUser;

        if (!ctx.request.files) {
            return ctx.apiFail('请先选择上传文件');
        }

        ctx.validate({
            dir_id: {
                type: "int",
                required: true,
                defValue: 0,
                desc: 'dir_id'
            },
        });

        const dir_id = ctx.query.dir_id;

        // 文件id是否存在
        if (dir_id > 0) {
            // 目录是否存在
            await this.service.file.isDirExist(dir_id);
        }

        const file = ctx.request.files[0];
        const name = 'egg-oss-demo/' + ctx.genID(10) + path.extname(file.filename);

        // 验证用户剩余内存是否满足要求 
        let s = await (new Promise((resolve, reject) => {
            fs.stat(file.filepath, (err, stats) => {
                resolve((stats.size / 1024).toFixed(1));
            });
        }));

        if ((currentUser.total_size - currentUser.used_size) < s) {
            return ctx.apiFail('你的可用内存不足');
        }

        let result;
        try {
            result = await ctx.oss.put(name, file.filepath);
        } catch (err) {
            console.log(err);
        }

        if (result) {
            // 写入数据表
            let addData = {
                name: file.filename,
                ext: file.mimeType,
                md: result.name,
                dir_id,
                user_id: currentUser.id,
                size: parseInt(s),
                isdir: 0,
                url: result.url
            };

            if (dir_id > 0) {
                addData.dir_id = dir_id;
            }

            let res = await app.model.File.create(addData);

            // 更新user表的使用内存
            currentUser.used_size = currentUser.used_size + parseInt(s);
            currentUser.save();

            return ctx.apiSuccess(res);
        }

        ctx.apiFail('上传失败');
    }
    //剩余容量
    async getSize() {
        const { ctx, service } = this;
        return ctx.apiSuccess({
            total_size: ctx.authUser.total_size,
            used_size: ctx.authUser.used_size,
        });
    }
    // 文件列表
    async list() {
        const { ctx, app } = this;
        const user_id = ctx.authUser.id;
        ctx.validate({
            dir_id: {
                required: true,
                type: "int",
                defValue: 0,
                desc: "目录id"
            },
            orderby: {
                required: false,
                type: "string",
                defValue: 'name',
                range: {
                    in: ['name', 'created_time']
                },
                desc: "排序"
            },
            type: {
                required: false,
                type: "string",
                desc: "类型"
            }
        });

        const { dir_id, orderby, type } = ctx.query;

        let where = {
            user_id,
            dir_id
        }

        if (type && type !== 'all') {
            const Op = app.Sequelize.Op;
            where.ext = {
                [Op.like]: type + '%',
            }
        }

        let rows = await app.model.File.findAll({
            where,
            order: [
                ['isdir', 'desc'],
                [orderby, 'desc']
            ]
        });

        ctx.apiSuccess({
            rows
        });
    }

    // 重命名
    async rename() {
        const { ctx, app } = this;
        const user_id = ctx.authUser.id;

        ctx.validate({
            id: {
                required: true,
                type: "int",
                desc: "文件记录id"
            },
            dir_id: {
                required: true,
                type: "int",
                defValue: 0,
                desc: "目录id"
            },
            name: {
                required: true,
                type: "string",
                desc: "文件名称"
            }
        });

        let { id, dir_id, name } = ctx.request.body;

        // 验证目录id是否存在
        if (dir_id > 0) {
            await this.service.file.isDirExist(dir_id);
        }

        // 文件或目录是否存在
        let f = await this.service.file.isExist(id);

        f.name = name;

        let res = await f.save();

        ctx.apiSuccess(res);
    }
    // 删除
    async delete() {
        const { ctx, app } = this;
        const user_id = ctx.authUser.id;

        ctx.validate({
            ids: {
                required: true,
                type: "string",
                desc: "记录"
            },
        });

        let { ids } = ctx.request.body;

        ids = ids.split(',');

        // 计算删除文件内存
        let files = await app.model.File.findAll({
            where: {
                id: ids,
                user_id
            }
        });

        let size = 0;
        files.forEach(item => {
            size = size + item.size
        });

        let res = await app.model.File.destroy({
            where: {
                id: ids,
                user_id
            }
        });

        if (res) {
            // 减去使用内存
            size = ctx.authUser.used_size - size;
            ctx.authUser.used_size = size > 0 ? size : 0;
            ctx.authUser.save();
        }

        ctx.apiSuccess(res);
    }
    // 搜索文件
    async search() {
        const { ctx, app } = this;
        const user_id = ctx.authUser.id;

        ctx.validate({
            keyword: {
                required: true,
                type: "string",
                desc: "关键字"
            },
        })

        let { keyword } = ctx.query

        const Op = app.Sequelize.Op

        let rows = await app.model.File.findAll({
            where: {
                name: {
                    [Op.like]: `%${keyword}%`
                },
                isdir: 0,
                user_id
            }
        })

        ctx.apiSuccess({
            rows
        })
    }
}

module.exports = FileController;
